﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Spanner
{
    public partial class UI
    {
        // These functions correspond one-to-one with their JavaScript counterparts.

        public static Expr<double> Abs(Expr<double> x) { return JSExpr<double>("Math.abs(#)", x); }
        public static Expr<double> Acos(Expr<double> x) { return JSExpr<double>("Math.acos(#)", x); }
        public static Expr<double> Asin(Expr<double> x) { return JSExpr<double>("Math.asin(#)", x); }
        public static Expr<double> Atan(Expr<double> x) { return JSExpr<double>("Math.atan(#)", x); }
        public static Expr<double> Atan2(Expr<double> x, Expr<double> y) { return JSExpr<double>("Math.atan2(#, #)", x, y); }
        public static Expr<int> Ceil(Expr<double> x) { return JSExpr<int>("Math.ceil(#)", x); }
        public static Expr<double> Cos(Expr<double> x) { return JSExpr<double>("Math.cos(#)", x); }
        public static Expr<double> E() { return JSExpr<double>("Math.E"); }
        public static Expr<double> Exp(Expr<double> x) { return JSExpr<double>("Math.exp(#)", x); }
        public static Expr<int> Floor(Expr<double> x) { return JSExpr<int>("Math.floor(#)", x); }
        public static Expr<double> Ln10() { return JSExpr<double>("Math.LN10"); }
        public static Expr<double> Ln2() { return JSExpr<double>("Math.LN2"); }
        public static Expr<double> Log10E() { return JSExpr<double>("Math.LOG10E"); }
        public static Expr<double> Log2E() { return JSExpr<double>("Math.LOG2E"); }
        public static Expr<double> Log(Expr<double> x) { return JSExpr<double>("Math.log(#)", x); }
        public static Expr<double> MaxDouble(Expr<double[]> xs)
        {
            return JSExpr<double>("Math.max.apply(null, #)", xs);
        }
        public static Expr<double> MaxDouble(params Expr<double>[] xs)
        {
            return new FmtExpr<double>(
                "Math.max",
                new FmtStr("Math.max"),
                new FmtParens(xs)
            );
        }
        public static Expr<int> MaxInt(Expr<int[]> xs)
        {
            return JSExpr<int>("Math.max.apply(null, #)", xs);
        }
        public static Expr<int> MaxInt(params Expr<int>[] xs)
        {
            return new FmtExpr<int>(
                "Math.max",
                new FmtStr("Math.max"),
                new FmtParens(xs)
            );
        }
        public static Expr<double> MinDouble(Expr<double[]> xs)
        {
            return JSExpr<double>("Math.min.apply(null, #)", xs);
        }
        public static Expr<int> MinInt(Expr<int[]> xs)
        {
            return JSExpr<int>("Math.min.apply(null, #)", xs);
        }
        public static Expr<double> MinDouble(params Expr<double>[] xs)
        {
            return new FmtExpr<double>(
                "Math.min",
                new FmtStr("Math.min"),
                new FmtParens(xs)
            );
        }
        public static Expr<int> MinInt(params Expr<int>[] xs)
        {
            return new FmtExpr<int>(
                "Math.min",
                new FmtStr("Math.min"),
                new FmtParens(xs)
            );
        }
        public static Expr<double> Pi() { return JSExpr<double>("Math.PI"); }
        public static Expr<double> Pow(Expr<double> x, Expr<double> y)
        {
            return JSExpr<double>("Math.pow(#, #)", x, y);
        }
        public static Expr<double> Random() { return JSExpr<double>("Math.random()"); }
        public static Expr<double> Round(Expr<double> x) { return JSExpr<double>("Math.round(#)", x); }
        public static Expr<double> Sin(Expr<double> x) { return JSExpr<double>("Math.sin(#)", x); }
        public static Expr<double> Sqrt(Expr<double> x) { return JSExpr<double>("Math.sqrt(#)", x); }
        public static Expr<double> Sqrt1_2() { return JSExpr<double>("Math.SQRT1_2"); }
        public static Expr<double> Sqrt2() { return JSExpr<double>("Math.SQRT2"); }
        public static Expr<double> Tan(Expr<double> x) { return JSExpr<double>("Math.tan(#)", x); }
    }
}
